﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using Raven.Client;

namespace Rabbit.Logic
{
    public class RabbitPunch
    {
        public static List<ProductSnapItem> PrepareProduct(Customer customer, List<ProductSnapWithQuantity> snaps)
        {
            List<ProductSnapItem> list = new List<ProductSnapItem>();

            for (int i = 0; i < customer.PreOrderShopItem.CartItemList.Count; i++)
            {
                ShopCartItem shopCartItem = customer.PreOrderShopItem.CartItemList[i];
                Product product = RabbitUse.GetProductById(Db.Store, shopCartItem.ProductId);
                string snapIndex = NoDb.GetSnapIndex(product);
                ProductSnap productSnap = RabbitUse.GetProductSnapBySnapIndex(Db.Store, snapIndex);
                if (productSnap == null)
                {
                    productSnap = NoDb.GetProductSnap(product);
                    RabbitUse.AddProductSnap(Db.Store, productSnap);
                }
                snaps.Add(new ProductSnapWithQuantity() { Product = productSnap, Quantity = shopCartItem.Quantity });

                ProductSnapItem productSnapItem = new ProductSnapItem();
                productSnapItem.ProductSnapId = productSnap.Id;
                productSnapItem.Quantity = shopCartItem.Quantity;
                list.Add(productSnapItem);
            }

            return list;
        }

        public static CustomerOrderMapping PrepareCustomerOrderMapping(Customer customer)
        {
            CustomerOrderMapping customerOrderMapping;
            if (string.IsNullOrEmpty(customer.OrderMappingId))
            {
                customerOrderMapping = new CustomerOrderMapping() { CustomerId = customer.Id, OrderIdList = new List<string>() };
                RabbitUse.AddCustomerOrderMapping(Db.Store, customerOrderMapping);
                customer.OrderMappingId = customerOrderMapping.Id;
                RabbitUse.AddOrUpdateCustomer(Db.Store, customer);
            }
            else
            {
                customerOrderMapping = RabbitUse.GetCustomerOrderMappingById(Db.Store, customer.OrderMappingId);
            }

            return customerOrderMapping;
        }

        public static ShopOrderMapping PrepareShopOrderMapping(Shop shop)
        {
            ShopOrderMapping shopOrderMapping;
            if (string.IsNullOrEmpty(shop.OrderMappingId))
            {
                shopOrderMapping = new ShopOrderMapping() { ShopId = shop.Id, OrderIdList = new List<string>(), OrderIdListNew = new List<string>(), OrderIdListSent = new List<string>(), OrderIdListDone = new List<string>()};
                RabbitUse.AddShopOrderMapping(Db.Store, shopOrderMapping);
                shop.OrderMappingId = shopOrderMapping.Id;
                RabbitUse.AddOrUpdateShop(Db.Store, shop);
            }
            else
            {
                shopOrderMapping = RabbitUse.GetShopOrderMappingById(Db.Store, shop.OrderMappingId);
            }

            return shopOrderMapping;
        }

        public static ShopOrderMapping CorrectShopOrderMapping(Shop shop)
        {
            ShopOrderMapping shopOrderMapping = RabbitUse.GetShopOrderMappingById(Db.Store, shop.OrderMappingId);
            shopOrderMapping.OrderIdListNew = new List<string>();
            shopOrderMapping.OrderIdListSent = new List<string>();
            shopOrderMapping.OrderIdListDone = new List<string>();
            foreach (var oid in shopOrderMapping.OrderIdList)
            {
                Order order = RabbitUse.GetOrderById(Db.Store, oid);
                if (order.State == OrderState.WaitPayment || order.State == OrderState.Paid || order.State == OrderState.WaitPackage) shopOrderMapping.OrderIdListNew.Add(oid);
                if (order.State == OrderState.Sent) shopOrderMapping.OrderIdListSent.Add(oid);
                if (order.State == OrderState.Confirmed || order.State == OrderState.Canceled) shopOrderMapping.OrderIdListDone.Add(oid);
            }
            RabbitUse.AddShopOrderMapping(Db.Store, shopOrderMapping);

            return shopOrderMapping;
        }

        public static string AddOrder(IDocumentStore store, Order order, CustomerOrderMapping customerOrderMapping, ShopOrderMapping shopOrderMapping)
        {
            //http://ravendb.net/docs/article-page/3.0/Csharp/client-api/session/transaction-support/dtc-transactions

            string msg = null;
            ValidationResult result = ValidateOrder(order);
            if (result == ValidationResult.Success)
            {
                using (IDocumentSession session = store.OpenSession())
                {
                    session.Store(order);

                    customerOrderMapping.OrderIdList.Add(order.Id);
                    session.Store(customerOrderMapping, customerOrderMapping.Id);
                    
                    shopOrderMapping.OrderIdList.Add(order.Id);
                    shopOrderMapping.OrderIdListNew.Add(order.Id);
                    session.Store(shopOrderMapping, shopOrderMapping.Id);

                    OrderLog log = new OrderLog();
                    log.OrderId = order.Id;
                    log.LogList = new List<string>();
                    log.LogList.Add(string.Format("{0} 订单创建", DateTime.Now));
                    session.Store(log);
                    order.OrderLogId = log.Id;
                    session.Store(order);

                    session.SaveChanges();
                }
            }
            else
            {
                msg = result.ErrorMessage;
            }

            return msg;
        }

        public static ValidationResult ValidateOrder(Order item)
        {
            var result = new ValidationResult(string.Empty);

            if (item == null)
            {
                result.ErrorMessage = "cannot be null.";
                return result;
            }

            if (string.IsNullOrEmpty(item.CustomerId))
            {
                result.ErrorMessage = "CustomerId is required.";
                return result;
            }

            if (item.Items == null || item.Items.Count == 0)
            {
                result.ErrorMessage = "Items is required.";
                return result;
            }

            return ValidationResult.Success;
        }



        public static bool RemoveBought(IDocumentStore store, Customer customer)
        {
            List<ShopCartItem> itemList = new List<ShopCartItem>();
            ShopItem targetShopItem = null;

            foreach (var shopItem in customer.ShopList)
            {
                if (shopItem.ShopId == customer.PreOrderShopItem.ShopId)
                {
                    targetShopItem = shopItem;

                    foreach (var item in shopItem.CartItemList)
                    {
                        if (customer.PreOrderShopItem.CartItemList.AsEnumerable().Any(x => x.ProductId == item.ProductId))
                        {
                            //shopItem.CartItemList.Remove(item);
                        }
                        else
                        {
                            itemList.Add(item);
                        }
                    }

                    break;
                }
            }

            if (itemList.Count > 0)
            {
                targetShopItem.CartItemList = itemList;
            }
            else
            {
                customer.ShopList.Remove(targetShopItem);
            }

            using (IDocumentSession session = store.OpenSession())
            {
                session.Store(customer, customer.Id);
                session.SaveChanges();
            }
            return true;
        }


        public static OrderViewCustomer GetOrderViewCustomer(IDocumentStore store, Order order)
        {
            OrderViewCustomer orderViewCustomer = new OrderViewCustomer();
            orderViewCustomer.OrderInfo = order;

            List<ProductSnapWithQuantity> list = new List<ProductSnapWithQuantity>();
            using (IDocumentSession session = store.OpenSession())
            {
                orderViewCustomer.ShopInfo = session.Query<Shop>().FirstOrDefault(x => x.ShopId == order.ShopId);

                foreach (var item in order.Items)
                {
                    ProductSnap productSnap = session.Load<ProductSnap>(item.ProductSnapId);
                    ProductSnapItem productSnapItem = order.Items.FirstOrDefault(x => x.ProductSnapId == productSnap.Id);
                    int quantity = productSnapItem == null ? 0 : productSnapItem.Quantity;
                    ProductSnapWithQuantity productSnapWithQuantity = new ProductSnapWithQuantity() {Product = productSnap, Quantity = quantity};
                    list.Add(productSnapWithQuantity);
                }
            }

            orderViewCustomer.ProductSnapWithQuantityList = list;

            return orderViewCustomer;
        }

        public static OrderViewShop GetOrderViewShop(IDocumentStore store, Order order)
        {
            OrderViewShop orderViewShop = new OrderViewShop();
            orderViewShop.OrderInfo = order;

            List<ProductSnapWithQuantity> list = new List<ProductSnapWithQuantity>();
            using (IDocumentSession session = store.OpenSession())
            {
                orderViewShop.CustomerInfo = session.Load<Customer>(order.CustomerId);

                foreach (var item in order.Items)
                {
                    ProductSnap productSnap = session.Load<ProductSnap>(item.ProductSnapId);
                    ProductSnapItem productSnapItem = order.Items.FirstOrDefault(x => x.ProductSnapId == productSnap.Id);
                    int quantity = productSnapItem == null ? 0 : productSnapItem.Quantity;
                    ProductSnapWithQuantity productSnapWithQuantity = new ProductSnapWithQuantity() { Product = productSnap, Quantity = quantity };
                    list.Add(productSnapWithQuantity);
                }
            }

            orderViewShop.ProductSnapWithQuantityList = list;

            return orderViewShop;
        }

        public static bool IsShopOrder(string ShopId, string orderId)
        {
            bool result = false;


            return result;
        }
    }
}
